#ifndef _DISPLAY_MODEL_H_
#define _DISPLAY_MODEL_H_

#include <QObject>
#include <QModelIndex>
#include <QPair>
#include <QStack>
#include <QVector4D>

#include "vtkImageData.h"
#include "vtkActor.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkDataSetMapper.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkSphere.h"
#include "vtkLineSource.h"
#include "vtkTubeFilter.h"

#include "Source.h"

class View3D;
class DisplayFramework;
class PipelineModel;

typedef struct _branch_display_structure
{
	QPair<int,int> branchID;
	vtkPolyData* polyData;
	vtkTubeFilter* tubeFilter;
	vtkPolyDataMapper* polyDataMapper;
	vtkActor* actor;
	QPair<QVector4D, QVector4D> pairStartEnds;
	QList<QVector4D> listBranchVolumeData;
}BranchInfo_t;


class DisplayModel : public QObject
{
	Q_OBJECT

public:
	DisplayModel();
	~DisplayModel();

	void setDisplayFramework(DisplayFramework*);
	void setPipelineModel(PipelineModel*);

	bool isDisplayingModel(const QModelIndex&);
	bool isDisplayingOutline(const QModelIndex&);
	//bool isDisplayingVolume(const QModelIndex&);
	bool isDisplaying2D(const QModelIndex&);

	vtkRenderWindowInteractor* activeInteractor();
	DisplayFramework* displayFramework()
	{
		return m_displayFramework;
	}

	QString currentSeed();
	int* currentSeedInt();

	vtkDataSet *getSelectedPoints()
	{
		return vtkDataSet::SafeDownCast(m_extractor->GetOutput());;
	}

	void getVisiblePropBounds(double *bounds);

	void resetCamera();
	void updateActive3DScene();

	// Add Primitive
	void addSphere(const QString& text);
	void addSphere(double x, double y, double z, double r);
	bool isSphereExisted(const QString& text);
	bool isASphere(vtkActor* actor);
	void removeSphere(const QString& text);
	void removeAllSpheres();
	void setSphereVisible(const QString& text, bool on);
	void setSphereRadiusRange(double from, double to);
	QString getSpherePosition(vtkActor* actor);
	int findSphere(const QString& text);
	int findSphere(const vtkActor* actor);


	bool isALine(vtkActor* actor);
	void addLine(const QString& src, const QString& dst);
	void addLine(double startx, double starty, double startz,
		double endx, double endy, double endz);
	void addLine(double start[3],double end[3]);
	void getLineProperty(vtkActor* actor, double start[3], double end[3]);

	void addBranch(QList<QVector4D> pointlist, int nid, int bid);
	bool isABranch(vtkActor *actor);
	QPair<int,int> getBranchID(vtkActor* actor);
	void removeABranch(vtkActor* actor, bool allChildren = true);
	void removeABranch(int nid, int bid);
	void setSelectABranch(vtkActor* actor, bool selected, int color=0);
	void setSelectABranch(QList<QVector4D> branch, int color=0);
	void clearSelectedBranches();
	void removeRebuiltBranches();

	QList<QList<QVector4D>> getSelectedBranch();

	void setBranchClass(int bclass, QVector4D startnode, QVector4D endnode);

	void addActor(vtkActor* actor);

public slots:
	void slotStartCutting();
	void slotStopCutting();
	void slotDoCut();

	void slotDisplayOutline(const QModelIndex&, bool flag=true);
	void slotDisplayModel(const QModelIndex&, bool flag=true);
	//void slotDisplayVolume(const QModelIndex&, bool flag=true);
	void slotDisplay2DSlices(const QModelIndex&, bool flag=true);
	void slotBlendImage(const QModelIndex&, bool flag);
	
	void slotSetBaseSource(const QModelIndex&);

	
	void slotPropertyChanged(Source*, SourceProperty);

	// real time slicing
	void slotStartRealTimeSlicing(Source*);
	void slotUpdateRealTimeSlicing(vtkImageData*, int);
	void slotStopRealTimeSlicing();


	// pick a seed from 2d view
	void slotPickSeed();						// pick a seed
	void slotRemoveSeed(QString);
	void slotSeedSelected(QString);		// select a seed point




private slots:
	void slotSeedPicked();
	void slotViewActivated(int);

private:
	void thresholdChanged(Source*);
	void removeSphere(int i);

signals:
	void emitUpdateSeeds(const QStringList&);		// seed back seed point


private:
	DisplayFramework *m_displayFramework;
	PipelineModel *m_pipelineModel;
	vtkExtractSelectedFrustum *m_extractor;
	vtkDataSetMapper *m_selectedMapper;
	vtkActor *m_selectedActor;
	View3D *m_cuttingView;
	View3D *m_rtView;
	Source *m_realTimeSource;
	double m_rtsSpacing[3];

	//pg::Image *m_pgImage;
	int				m_pgFDMethod;

	QList<QString> m_listSpherePosition;
	QList<vtkSphereSource*> m_listSphereSource;
	QList<vtkPolyDataMapper*> m_listSphereMapper;
	QList<vtkActor*> m_listSphereActor;

	QList<QList<double>> m_listLinePosition;
	QList<vtkLineSource*> m_listLineSource;
	QList<vtkPolyDataMapper*> m_listLineMapper;
	QList<vtkActor*> m_listLineActor; 

	int m_selectedIndex;
	QList<int> m_listSelectedIndics;
	QStack<vtkActor*> m_listSelectedBranchActor;

	QList<BranchInfo_t*> m_listBranchInfo;

// 	QList<vtkPolyData*> m_listBranchData;
// 	QList<vtkTubeFilter*> m_listBranchTube;
// 	QList<vtkPolyDataMapper*> m_listBranchMapper;
// 	QList<vtkActor*> m_listBranchActor;
// 	QList<QPair<QVector4D, QVector4D>> m_listStartEnds;
// 	QList<QList<QVector4D>> m_listBranchVolumeData;
// 	QList<QPair<int,int>> m_listBranchID;
};



#endif

